package com.kool.kmqtt.server.exception;

import lombok.Getter;

import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Getter
public enum ErrorCode {
    SUCCESS(0, "成功"),
    //MQTT协议约定异常
    CHARSET_NOT_UTF8(1, "UTF-8解码失败"),
    NOT_MQTT_PROTOCOL(2, "非MQTT协议"),
    UNSUPPORTED_PROTOCOL_LEVEL(3, "不支持的协议等级"),
    CONNECT_FLAGS_RESERVED_NOT_ZERO(4, "CONNECT报文的connect flags保留标志位（第0位）不为0"),
    DUP_ERROR(5, "对于QoS 0的消息，DUP标志必须设置为0"),
    QOS_ERROR(6, "QoS 必须等于 0/1/2"),
    TOPIC_NAME_ERROR(7, "主题名错误[%s]"),
    PUBREL_FLAGS_ERROR(8, "PUBREL保留位必须为0010"),
    SUBSCRIBE_FLAGS_ERROR(9, "SUBSCRIBE保留位必须为2"),
    SUBSCRIBE_INFO_NULL(10, "有效载荷必须包含至少一对主题过滤器 和 QoS等级字段组合"),
    SUBSCRIBE_QOS_ERROR(11, "QoS必须等于0,1或2"),
    UNSUBSCRIBE_FLAGS_ERROR(12, "UNSUBSCRIBE保留位必须为2"),
    UNSUBSCRIBE_INFO_NULL(13, "有效载荷必须包含至少一个主题过滤器"),
    DISCONNECT_FLAGS_ERROR(14, "SUBSCRIBE保留位必须为0"),
    MAX_LENGTH_ERROR(15, "报文长度超过最大允许长度，可变报头+载荷的最大允许长度为256MB"),
    USER_PASSWORD_FLAG_ERROR(16, "如果用户名标志被设置为0，密码标志也必须设置为0"),

    //非MQTT协议约定异常
    PACKET_ID_POOL_IS_EMPTY(1001, "客户端[%s]的报文id已用尽!"),
    PACKET_ID_POOL_SIZE_ERROR(1002, "报文id资源池容量必须大于0，小于等于50000"),
    UNSUPPORTED_REPOSITORY_TYPE(1003, "不支持的仓库类型[%s]"),
    SAVE_PACKET_ID_NULL(1004, "保存报文时，报文id为空"),
    DELETE_PACKET_ID_NULL(1005, "删除报文时，报文id为空"),
    SAVE_WILL_STATUS_CLIENT_ID_NULL(1006, "保存遗嘱信息时，客户端id为空"),
    DELETE_WILL_STATUS_CLIENT_ID_NULL(1007, "删除遗嘱信息时，客户端id为空"),
    CLIENT_ID_NULL(1008, "客户端id不能为空"),
    ETCD_ERROR(1009, "ETCD访问异常：%s"),
    TOPIC_NULL(1010, "主题名不能为空"),
    TOPIC_FILTER_FORMAT_ERROR(1011, "主题过滤器格式错误"),
    UNDEFINED_PACKET_TYPE(1012, "未定义的报文类型:%s"),
    HTTP_ERROR(1013, "访问外部服务【%s】发生异常:%s"),
    USERNAME_NULL(1014,"用户名不能为空"),
    PASSWORD_NULL(1015,"密码不能为空"),
    USER_PASSWORD_AUTH_ERROR(1016,"用户密码验证失败，次数：%s，原因：%s"),
    NO_TOPIC_PERMIT(1017,"用户没有主题权限");

    Integer code;
    String message;

    ErrorCode(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public static Map<Integer, ErrorCode> codeToEnum = Stream.of(ErrorCode.values()).collect(Collectors.toMap(ErrorCode::getCode, self -> self));

    public static ErrorCode getEnumByCode(Integer errorCode) {
        return codeToEnum.get(errorCode);
    }

    public static String getMsgByCode(Integer errorCode) {
        return codeToEnum.get(errorCode) == null ? null : codeToEnum.get(errorCode).getMessage();
    }
}
